//在系统的角度上面封装一层去进行多线程演示
//语言的角度：c++
#include <iostream>
#include <unistd.h>
#include <thread>

void thread_run()
{
    while (true)
    {
        std::cout << "我是新线程..." << std::endl;
        sleep(1);
    }
}

int main()
{
    // 任何语言，在linux中如果要实现多线程，必定要是用pthread库
    // 如何看待C++11中的多线程呢？？C++11 的多线程，在Linux环境中，本质是对pthread库的封装！
    std::thread t1(thread_run);

    while (true)
    {
        std::cout << "我是主线程..." << std::endl;
        sleep(1);
    }

    t1.join();

    return 0;
}







//这下面的代码是站在系统的角度去演示的线程的退出

// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <pthread.h>
// #include <string.h>
// #include <vector>
// #include <unistd.h>
// using namespace std;
// #define Num 10
// class Thread_Data{
// public:
//     pthread_t id;
//     char namebuffer[64];
//     long long num;  //线程退出码，可以定义在这里面
// };

// class ThreadReturn{
// public:
//     int exit_code;
//     int exit_result;

// };

// // 1. stat_routine，是被几个线程执行呢？ 被10个线程执行，这个函数是可重入状态
// // 2.该函数时可重入函数嘛？是可重入函数、
// // 3.在函数内定义的变量，叫做局部变量，具有临时性--依旧适用--在多线程的情况下，没有问题
// // 从实验结果来看，每个线程的cnt没有被共享，所以每个线程都有自己独立的栈结构
// void *stat_routine(void* args)
// {
//     string str = static_cast<char*>(args);   //static_cast<>  安全的强制类型转换
//     Thread_Data* td = static_cast<Thread_Data*>(args);
//     int cnt=10;
//     while(cnt--)
//     {
//         cout << "cnt: " << cnt << " &cnt: " << &cnt << endl; // bug       
//         sleep(1);

//         // int* p=nullptr;
//         // p=nullptr;  //不报错
//         // *p = 0;  //报错，在修改nullptr处的地址，此时整个进程会退出，只有线程出错，整个进程都会退出
//         // exit(0);     //这不是线程退出，这是整个进程退出，任何一个执行流调用这个exit都会中止进程的
//     }
//     //线程退出方式：可以使用return   可以使用pthread_exit()
//     //pthread_exit((void*)td->num);   //线程退出的函数  pthread_exit(void *retval);
//     //

//     //return (void*)td->num; // warning void* ret = (void*)td->number

//     // //也可以单独封装一个类去接收这个值
//     // ThreadReturn* tr =new ThreadReturn();
//     // tr->exit_code=1;
//     // tr->exit_result=111;
//     // return (void*)tr;  //同样可以返回，这里是个右值，是需要拷贝的

//     //return nullptr;     //这里是有返回值的，返回值以后线程结束

//     return (void*)100;  //右值
// }

// int main()
// {

// vector<Thread_Data*>  td;
//     //创建10个子线程
//     for(int i=0;i<Num;++i)
//     {
//         Thread_Data* pid = new Thread_Data();   //在堆上创建这些数据
//         snprintf(pid->namebuffer,sizeof(pid->namebuffer),"%s：%d","threadnum",i+1);
//         pid->num=i+1;
//         pthread_create(&pid->id,nullptr,stat_routine,(void*)pid);    //这是系统级别的调用接口，还有vfork也是创建进程的，还有clone函数也是创建进程的
//         td.push_back(pid);
//     }
//     sleep(5);
//     for(auto &xpid:td)
//     {
//         cout<<"name:"<<xpid->namebuffer<<"  id:"<<xpid->id<<endl;
//     }

//     //线程同样是可以被取消的，取消后的退出码 是-1
//     //线程被取消的前提是：这个线程已经跑起来的
//     //函数 pthread_canncel
//     for(int i=0;i<td.size()/2;++i)
//     {
//         pthread_cancel(td[i]->id);  //取消线程的运行  int pthread_cancel(pthread_t thread);
//         cout<<"pthread_cancel : "<<td[i]->namebuffer<<"success"<<endl;


//     }


//     //主函数一般是回收子线程的
//     for(auto &xpid:td)
//     {
//         void* ret=0;        //注意这里是void* 类型的数据

//          // ? : 为什么没有见到，线程退出的时候，对应的退出信号？？？ 线程出异常，收到信号，整个进程都会退出！
//          // pthread_join:默认就认为函数会调用成功！不考虑异常问题，异常问题是你进程该考虑的问题！
//         int n = pthread_join(xpid->id,(void**)&ret);  //void ** retp ; *retp = return (void*)td->number   第二个参数是个输出型参数
//         cout<<"回收子线程,namebuffer="<<xpid->namebuffer<<" 线程退出码xipd->num  "<<(long long*)ret<<endl;
//         delete xpid;
//         xpid=nullptr;
//     }

//     sleep(5);
//     cout<<"main thread quit"<<endl;


//     // pthread_t ptd;
//     // int n=pthread_create(&ptd,nullptr,stat_routine,(void*)"thread one");
//     // while(true)
//     // {
//     //     cout<<"main thread"<<endl;
//     //     sleep(1);
//     // }

//     return 0;
// }